package cn.siriusbot.siriuspro.bot.api.impl;

import cn.siriusbot.siriuspro.bot.api.GroupApi;
import cn.siriusbot.siriuspro.bot.api.pojo.qq.GeneralMessageResult;
import cn.siriusbot.siriuspro.bot.api.pojo.message.Message;
import cn.siriusbot.siriuspro.bot.api.pojo.message.MessageKeyboard;
import cn.siriusbot.siriuspro.bot.api.pojo.message.MessageMarkdown;
import cn.siriusbot.siriuspro.bot.api.pojo.message.ark.MessageArk;
import cn.siriusbot.siriuspro.bot.api.tuple.Tuple;
import cn.siriusbot.siriuspro.bot.client.BotClient;
import cn.siriusbot.siriuspro.bot.event.BotHttpEvent;
import cn.siriusbot.siriuspro.bot.pojo.BotRequest;
import cn.siriusbot.siriuspro.bot.pojo.BotResponse;
import cn.siriusbot.siriuspro.bot.pojo.e.RequestMethod;
import cn.siriusbot.siriuspro.config.bean.BotPool;
import com.alibaba.fastjson.JSONObject;
import com.vdurmont.emoji.EmojiParser;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class GroupApiImpl implements GroupApi {

    @Autowired
    BotPool botPool;

    /**
     * 通用发送消息
     *
     * @param bot_id            传入机器人ID
     * @param group_id          群ID
     * @param content           要发送的消息内容
     * @param msg_type          消息类型： 0 文本，2 是 markdown，3 ark 消息，4 embed，7 media 富媒体
     * @param markdown          markdown对象
     * @param keyboard          按钮对象
     * @param media             {file_info: \"\"} 数据来源\"消息收发=>富媒体消息\"
     * @param ark               ark消息对象
     * @param image             【暂不支持】图片
     * @param message_reference 【暂未支持】消息引用
     * @param event_id          事件ID
     * @param msg_id            消息ID
     * @param msg_seq           回复消息的序号，与 msg_id 联合使用，避免相同消息id回复重复发送，不填默认是 1。相同的 msg_id + msg_seq 重复发送会失败。
     * @return 消息对象
     */
    @Override
    public Tuple<GeneralMessageResult, String> sendGeneralMessage(@NonNull String bot_id, @NonNull String group_id, String content, Integer msg_type, MessageMarkdown markdown, MessageKeyboard keyboard, String media, MessageArk ark, String image, String message_reference, String event_id, String msg_id, String msg_seq) {
        BotClient client = botPool.getBotById(bot_id);
        BotHttpEvent http = client.getBean(BotHttpEvent.class);

        content = EmojiParser.parseToUnicode(content);
        BotRequest botRequest = new BotRequest()
                .addHeader("Authorization", "QQBot " + http.getAccessToken())
                .setMethod(RequestMethod.POST)
                .setUrl(client.getSession().getOpenUrl() + "v2/groups/" + group_id + "/messages")
                .setMediaType("text/plain;application/json")
                .putRequestBody("content", content)
                .putRequestBody("msg_type", msg_type)
                .putRequestBody("markdown", markdown)
                .putRequestBody("keyboard", keyboard)
                .putRequestBody("media", JSONObject.parseObject(media))
                .putRequestBody("ark", ark)
                .putRequestBody("image", image)
                .putRequestBody("message_reference", message_reference)
                .putRequestBody("message_reference", JSONObject.parseObject(message_reference))
                .putRequestBody("event_id", event_id)
                .putRequestBody("msg_id", msg_id)
                .putRequestBody("msg_seq", msg_seq)
                .putRequestBody("timestamp", System.currentTimeMillis());

        BotResponse response = http.req(botRequest);
        Tuple<GeneralMessageResult, String> tuple = new Tuple<>();
        try {
            tuple
                    .setFirst(JSONObject.parseObject(response.getBody(), GeneralMessageResult.class))
                    .setSecond(response.getBody());
        } catch (Throwable e) {
            tuple.setFirst(null).setSecond(response.getBody());
        }

        return tuple;
    }

    /**
     * 用于向 channel_id 指定的子频道发送消息。
     * 要求机器人在该子频道具有发送消息的权限。
     * 主动消息在频道主或管理设置了情况下，按设置的数量进行限频。在未设置的情况遵循如下限制:
     * 主动推送消息，默认每天往每个子频道可推送的消息数是 20 条，超过会被限制。
     * 主动推送消息在每个频道中，每天可以往 2 个子频道推送消息。超过后会被限制。
     * 不论主动消息还是被动消息，在一个子频道中，每 1s 只能发送 5 条消息。
     * 被动回复消息有效期为 5 分钟。超时会报错。
     * 发送消息接口要求机器人接口需要连接到 websocket 上保持在线状态
     * 有关主动消息审核，可以通过 Intents 中审核事件 MESSAGE_AUDIT 返回 MessageAudited 对象获取结果。
     * 如传入event_id和msg_id其中一个，此条消息视为被动消息
     *
     * @param bot_id   传入机器人ID
     * @param group_id 群ID
     * @param content  要发送的消息内容
     * @param msg_id   消息ID
     * @return 消息对象
     */
    @Override
    public Tuple<Message, String> sendMessage(@NonNull String bot_id, @NonNull String group_id, String content, String msg_id) {
        BotClient client = botPool.getBotById(bot_id);
        BotHttpEvent http = client.getBean(BotHttpEvent.class);

        content = EmojiParser.parseToUnicode(content);
        BotRequest botRequest = new BotRequest()
                .addHeader("Authorization", "QQBot " + http.getAccessToken())
                .setMethod(RequestMethod.POST)
                .setUrl(client.getSession().getOpenUrl() + "v2/groups/" + group_id + "/messages")
                .setMediaType("text/plain;application/json")
                .putRequestBody("content", content)
                .putRequestBody("msg_id", msg_id)
                .putRequestBody("timestamp", System.currentTimeMillis());

        BotResponse response = http.req(botRequest);
        Tuple<Message, String> tuple = new Tuple<>();
        tuple
                .setFirst(JSONObject.parseObject(response.getBody(), Message.class))
                .setSecond(response.getBody());
        return tuple;
    }

    /**
     * 用于发送QQ好友发送富文本消息
     *
     * @param bot_id       机器人ID
     * @param group_id     群ID
     * @param content      消息内容
     * @param event_id     事件ID
     * @param file_type    文件类型
     * @param url          文件地址
     * @param srv_send_msg 服务器消息
     * @return 消息对象
     */
    @Override
    public Tuple<Message, String> sendRichMediaMessage(@NonNull String bot_id, @NonNull String group_id, String content, String event_id, Integer file_type, String url, Boolean srv_send_msg) {
        BotClient client = botPool.getBotById(bot_id);
        BotHttpEvent http = client.getBean(BotHttpEvent.class);

        if (content != null) content = EmojiParser.parseToUnicode(content);
        BotRequest botRequest = new BotRequest()
                .addHeader("Authorization", "QQBot " + http.getAccessToken())
                .setMethod(RequestMethod.POST)
                .setUrl(client.getSession().getOpenUrl() + "v2/groups/" + group_id + "/files")
                .setMediaType("text/plain;application/json")
                .putRequestBody("content", content)
                .putRequestBody("event_id", event_id)
                .putRequestBody("file_type", file_type)
                .putRequestBody("url", url)
                .putRequestBody("srv_send_msg", srv_send_msg)
                .putRequestBody("timestamp", System.currentTimeMillis());


        BotResponse response = http.req(botRequest);
        Tuple<Message, String> tuple = new Tuple<>();
        tuple
                .setFirst(JSONObject.parseObject(response.getBody(), Message.class))
                .setSecond(response.getBody());
        return tuple;
    }

    /**
     * 发送markdown消息(富文本)
     * 要求操作人在该子频道具有发送消息和对应 Markdown 模版 的权限。
     * 调用前开发者需要先在“QQ开放平台-机器人-发布设置-消息模板”入口为对应机器人创建申请Markdown消息模板，得到模板 id ，在请求时填在对应的 markdown.template_id 上。
     * 模板参数暂不支持数组。
     * 消息体中所包含的URL需要报备并通过验证，方可使用。
     * 如传入event_id和msg_id其中一个，此条消息视为被动消息
     *
     * @param bot_id   传入机器人ID
     * @param group_id 群ID
     * @param msg_id   消息id
     * @param event_id 事件ID
     * @param markdown markdown对象
     * @return 返回消息对象
     */
    @Override
    public Tuple<Message, String> sendMarkdownMessage(@NonNull String bot_id, @NonNull String group_id, String msg_id, String event_id, @NonNull MessageMarkdown markdown, MessageKeyboard keyboard) {
        BotClient client = botPool.getBotById(bot_id);
        BotHttpEvent http = client.getBean(BotHttpEvent.class);

        BotRequest botRequest = new BotRequest()
                .addHeader("Authorization", "QQBot " + http.getAccessToken())
                .setMethod(RequestMethod.POST)
                .setUrl(client.getSession().getOpenUrl() + "v2/groups/" + group_id + "/messages")
                .setMediaType("text/plain;application/json")
                .putRequestBody("timestamp", System.currentTimeMillis())
                .putRequestBody("content", "md")
                .putRequestBody("msg_type", 2)
                .putRequestBody("msg_id", msg_id)
                .putRequestBody("markdown", markdown)
                .putRequestBody("keyboard", keyboard);

        BotResponse response = http.req(botRequest);
        Tuple<Message, String> tuple = new Tuple<>();
        tuple
                .setFirst(JSONObject.parseObject(response.getBody(), Message.class))
                .setSecond(response.getBody());
        return tuple;
    }

}
